package bigo.data;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.hadoop.io.Writable;

/**
 * Stores all CONTINOUS rows belongs to a matrix
 * @author Song Liu (sl9885@bristol.ac.uk)
 */
public class Matrix implements Writable {

    private ArrayList<Vector> rowArrays = new ArrayList<Vector>();
    private int columnOffset;

    public Matrix() {
    }

    /**
     * Constructs a Matrix with given offset
     * @param colummnOffset offset
     */
    public Matrix(int colummnOffset) {
        this.columnOffset = colummnOffset;
    }

    public int getColumnOffset() {
        return columnOffset;
    }

    public void addRowVector(Vector v) {
        rowArrays.add(v);
    }

    public int getNumColumns() {
        return rowArrays.get(0).length();
    }

    public int getNumRows() {
        return rowArrays.size();
    }

    public float get(int i, int j) {
        if (getRowVectorAt(i).containsKey(j)) {
            return getRowVectorAt(i).get(j);
        }
        return .0f;
    }

    public Vector getRowVectorAt(int rowIndex) {
        return rowArrays.get(rowIndex - columnOffset);
    }

    public Vector getColumnVectorAt(int columnIndex) {
//        ArrayVector res = new ArrayVector(columnOffset, rowArrays.size());
//        for (int i = columnOffset; i < columnOffset + getNumRows(); i++) {
//            Float val = getRowVectorAt(i).get(columnIndex);
//            if (val!=null) {
//                res.put(i, val);
//            }
//        }
//        return res;
        return new VirtualColumnVector(this,columnIndex);
    }

    public ArrayList<Vector> getRowArrays() {
//        if(startsFrom != 0)
//            throw new IllegalArgumentException("Offset Not 0!");
        return rowArrays;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(
                "startsfrom:" + columnOffset + " " + "[");
        for (Vector v : rowArrays) {
            sb.append(v.toString() + "||");
        }
        return sb.toString() + "]";
    }

    public void write(DataOutput out) throws IOException {
        out.writeInt(rowArrays.size());
        out.writeInt(columnOffset);
        for (Vector v : rowArrays) {
            if (v instanceof HashVector) {
                out.writeBoolean(true);
            } else {
                out.writeBoolean(false);
            }
            v.write(out);
        }
    }

    public void readFields(DataInput in) throws IOException {
        rowArrays.clear();
        int len = in.readInt();
        columnOffset = in.readInt();

        for (int i = 0; i < len; i++) {
            boolean isHash = in.readBoolean();
            Vector v = null;
            if (isHash) {
                v = new HashVector();
            } else {
                v = new ArrayVector();
            }
            v.readFields(in);
            rowArrays.add(v);
        }
    }
}
